﻿using System;
using System.IO;
using System.Reflection;
using System.Text;



namespace Crm2011.Framework.Connect
{
    internal static class PublicFunc
    {
        /* 
         * My word wrap implementations as originally implemented in VB6 in the year 2005!
         * Since then it just works, I haven't refactored it. However, I found a quite interesting article here:
         * http://www.codeproject.com/Articles/51488/Implementing-Word-Wrap-in-C
         */


        public static string Wrap(string text, int atColumn=70)
        {
            StringBuilder sb = new StringBuilder(text.Replace(Environment.NewLine, "|"));
            sb.Replace("\r\n", "|");
            sb.Replace("\r", "|");
            sb.Replace("\n", "|");
            string[] lines = sb.ToString().Split('|');
            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Length > atColumn) lines[i] = insertLineBreaks(lines[i], atColumn);
            }
            return String.Join(Environment.NewLine, lines);
        }



        private static string insertLineBreaks(string line, int lineBreakColumn)
        {
            char[] lineBreaker = new char[] {' ', '-'};
            StringBuilder sb = new StringBuilder();

            int pStartSegment = 0;

            do
            {
                int pStartFind = pStartSegment + lineBreakColumn;
                int pEnd = line.LastIndexOfAny(lineBreaker, pStartFind);

                // cannot break line BEFORE lineBreakColumn --> insert hardbreak
                if (pEnd < pStartSegment) pEnd = pStartFind;

                sb.AppendLine(line.Substring(pStartSegment, pEnd - pStartSegment + 1).TrimEnd());
                pStartSegment = pEnd + 1;
            } while (pStartSegment < line.Length - lineBreakColumn);

            // add last Segment w/o NewLine
            sb.Append(line.Substring(pStartSegment, line.Length - pStartSegment));
            return sb.ToString();
        }



        /// <summary>
        /// Evaluates a <c>filePath</c> to a full, rooted <paramref name="filePath"/>. Environment variables will be replaced.
        /// </summary>
        /// <param name="filePath">Any relative or rooted <c>filePath</c>.</param>
        /// <param name="relativeTo">
        /// If <c>filePath</c> is relative it will be rooted to this directory.<br />
        /// If this parameter is null, Assembly.GetCallingAssembly().CodeBase is used 
        /// as the base path.
        /// </param>
        /// <param name="throwOnError">If the file does not exist, an exception will be thrown.</param>
        public static string GetFullFilePath(string filePath, string relativeTo, bool throwOnError)
        {
            string fullFilePath = Environment.ExpandEnvironmentVariables(filePath);

            if (fullFilePath.Contains("%MyDocuments%"))
                fullFilePath = fullFilePath.Replace("%MyDocuments%", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

            if (relativeTo != null) relativeTo = Environment.ExpandEnvironmentVariables(relativeTo);

            if (!Path.IsPathRooted(fullFilePath))
            {
                if (relativeTo == null)
                    relativeTo = Assembly.GetCallingAssembly().CodeBase;


                if (relativeTo.ToLower().StartsWith("file://"))
                {
                    Uri uriCodeBase = new Uri(relativeTo);
                    relativeTo = uriCodeBase.LocalPath;
                }


                // msc, 2008-08-14: test File.Exist before GetAttributes
                // if it's a file we need to file's directory as the relative basis
                if (File.Exists(relativeTo) && (File.GetAttributes(relativeTo) & FileAttributes.Directory) == 0)
                    relativeTo = Path.GetDirectoryName(relativeTo);

                fullFilePath = Path.GetFullPath(Path.Combine(relativeTo, filePath));
            }
            else
                fullFilePath = Path.GetFullPath(fullFilePath);


            if (fullFilePath.EndsWith(@"\") || Directory.Exists(fullFilePath))
            {
                if (!Directory.Exists(fullFilePath))
                {
                    //Trace.Default.Warn("GetFullFilePath check existence failed for directory {0}", fullFilePath);
                    if (throwOnError) throw new DirectoryNotFoundException(string.Format("Directory {0} not found.", fullFilePath));
                }
            }
            else
            {
                if (!File.Exists(fullFilePath))
                {
                    //Trace.Default.Warn("GetFullFilePath check existence failed for file {0}", fullFilePath);
                    if (throwOnError) throw new FileNotFoundException(string.Format("File {0} not found.", fullFilePath));
                }
            }

            //if (filePath != fullFilePath)
            //    Trace.Default.Debug("{0} has been completed to {1}", filePath, fullFilePath);

            return fullFilePath;
        }

    }
}